import 'package:dio/dio.dart';
import 'dart:convert';

import 'network_response.dart';

class NetworkCore {

  static const String GET = 'get';
  static const String POST = 'post';
  static const String PUT = 'put';
  static const String DELETE = 'delete';

  final Dio dio = new Dio();
  final CancelToken token = new CancelToken();
  //提交参数是否是formdata形式
  bool isFormData = true;

  //#############################构造方法#############################
  NetworkCore() {
    print('NetworkCore init');
    this.dio.options.connectTimeout = 5000; //5s
    this.dio.options.receiveTimeout = 5000; //5s
  }

  //#############################公开方法#############################
  //get请求
  void get(String url, {Map<String, dynamic> params, Function successCallBack, Function failureCallBack}) async {
    String appendUrl= "";
    if (params != null && params.isNotEmpty) {
      String paramString = _convertMapToString(params);
      appendUrl = "?"+paramString.substring(0,paramString.length-1);
    }
    fullUrlGet(url+appendUrl, successCallBack:successCallBack, failureCallBack:failureCallBack);
  }

  //post请求
  void post(String url, {Map<String, dynamic> params, Function successCallBack, Function failureCallBack}) async {
    _request(POST ,url, successCallBack, failureCallBack, params: params);
  }

  //put请求
  void put(String url, {Map<String, dynamic> params, Function successCallBack, Function failureCallBack}) async {
    _request(PUT ,url, successCallBack, failureCallBack, params: params);
  }

  //delete请求
  void delete(String url, {Map<String, dynamic> params, Function successCallBack, Function failureCallBack}) async {
    _request(DELETE ,url, successCallBack, failureCallBack, params: params);
  }

  //全路径get请求
  void fullUrlGet(String url, {Function successCallBack, Function failureCallBack}) async {
    _request(GET ,url, successCallBack, failureCallBack);
  }

  //取消所有请求
  void cancelAllRequests() {
      this.token.cancel('cancelled');
  }

  //#############################私有方法#############################
  //公共请求方法
  void _request(String method, String url, Function successCallBack, Function failureCallBack, {Map<String, dynamic> params}) async {

    print('<net> method:<'+method+'> url:' + url);

    bool hasParams = false;
    if (params != null && params.isNotEmpty) {
      hasParams = true;
      print('<net> params:' + params.toString());
    }

    String errorMsg = '';
    int statusCode;

    try {
      Response response;

      var data;
      if (hasParams && this.isFormData) {
        data = new FormData.from(params);
      } else {
        data = params;
      }

      if (method == GET) {
        response = await this.dio.get(url, cancelToken: this.token);
      } else if (method == POST) {
        response = await this.dio.post(url, data: data, cancelToken: this.token);
      } else if (method == PUT) {
        response = await this.dio.put(url, data: data, cancelToken: this.token);
      } else if (method == DELETE) {
        response = await this.dio.delete(url, data: data, cancelToken: this.token);
      }

      statusCode = response.statusCode;

      //处理错误部分
      if (statusCode < 0) {
        errorMsg = '网络请求错误,状态码:' + statusCode.toString();
        _handError(failureCallBack, errorMsg);
        return;
      }

      if (successCallBack != null) {
        NetworkSuccessResponse successResponse = new NetworkSuccessResponse();
        successCallBack(successResponse);
        print('<net> response data:' + response.data.toString());
      }
    } catch (exception) {
      if (exception is DioError && CancelToken.isCancel(exception)) {
        _handError(failureCallBack, '取消请求');
      } else {
        _handError(failureCallBack, exception.toString());
      }
    }
  }

  //处理异常
  static void _handError(Function callBack, String errorMsg) {
    if (callBack != null) {
      NetworkFailureResponse failureResponse = new NetworkFailureResponse();
      callBack(failureResponse);
    }
    print('<net> errorMsg :' + errorMsg);
  }

  //#############################工具方法#############################
  //转化参数方法
  static String _convertMapToString(Map<String, dynamic> params) {
    String paramsString = "";
    params.forEach((key, value) {
      String itemString = "";
      if (value is Map) {
        itemString = value.toString();
      } else if (value is List) {
        itemString = _convertListToString(key,value);
      } else {
        itemString = key+'='+value.toString()+'&';
      }
      paramsString += itemString;
    });
    return paramsString;
  }

  static  String _convertListToString(String key,List params) {
    String paramsString = "";
    params.forEach((value) {
      String itemString = "";
      if (value is Map) {
        itemString = value.toString();
      } else if (value is List) {
        itemString = _convertListToString(key,value);
      } else {
        itemString = key+'='+value.toString()+'&';
      }
      paramsString += itemString;
    });
    return paramsString;
  }
}
